#include "wm_include.h"
#include "multi_light.h"

#define LIGHT_TIMER_TIME     (float)HZ/100            // 10ms
#define LIGHT_TICKS          10                       // 10ms/tick

static tls_os_timer_t *TICKS_TIMER = NULL;
static struct Light* head_handle = NULL;

static void light_ticks(void *ptmr, void *parg);
static void light_handler(struct Light* handle);

void light_init(struct Light* handle, enum tls_io_name gpio_pin, uint8_t active_level)
{
	if(active_level)
	{
		// printf("--->gpio:%d attribute:%d\r\n",gpio_pin,WM_GPIO_ATTR_PULLLOW);
		tls_gpio_cfg(gpio_pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLLOW);
		tls_gpio_write(gpio_pin,0);
	}
	else
	{
		// printf("--->gpio:%d attribute:%d\r\n",gpio_pin,WM_GPIO_ATTR_PULLHIGH);
		tls_gpio_cfg(gpio_pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
		tls_gpio_write(gpio_pin,1);
	}
	memset(handle, 0, sizeof(struct Light));
	handle->light_gpio = gpio_pin;
	handle->active_level = active_level;
	handle->last_level = !active_level;
	if (NULL == TICKS_TIMER)
	{
		tls_os_timer_create(&TICKS_TIMER,light_ticks,NULL,LIGHT_TIMER_TIME,TRUE,NULL);  // Create button ticks timer
	}
	tls_os_timer_start(TICKS_TIMER);
}
static void light_ticks(void *ptmr, void *parg)
{
	struct Light* target;
	for(target=head_handle; target; target=target->next) {
		light_handler(target);
	}
}

static void light_handler(struct Light* handle)
{
	// handle->ticks*LIGHT_TIMER - handle->last_time > handle->last_time;
    // printf("%d\r\n",handle->light_gpio);
	if(handle->keep_ticks)
	{
		handle->keep_ticks--;
		// printf("%d\r\n",handle->keep_ticks);
		if(!handle->keep_ticks)
		{
			handle->ticks = 0;
			handle->state = 0;
			tls_gpio_write(handle->light_gpio,!handle->active_level);
			handle->last_level = !handle->active_level;
			// printf("--->timeout\r\n");
		}
	}
	//ticks counter working..
	if((handle->state) > 0) handle->ticks++;

	/*-----------------State machine-------------------*/

	switch (handle->state) {
	case 0:
		// What also not stem
		break;
	case 1:
		if(handle->last_level != handle->active_level)
		{
			tls_gpio_write(handle->light_gpio,handle->active_level);
			handle->last_level = handle->active_level;
			// printf("--->state:%d\r\n",handle->state);
		}
		break;
	case 2:
		if(handle->last_level == handle->active_level)
		{
			tls_gpio_write(handle->light_gpio,!handle->active_level);
			handle->last_level = !handle->active_level;
			// printf("--->state:%d\r\n",handle->state);
		}
		break;
	case 3:
		if(handle->ticks - handle->last_ticks > handle->high_level_ticks)
		{
			tls_gpio_write(handle->light_gpio,handle->active_level);
			handle->last_level = handle->active_level;
			handle->last_ticks = handle->ticks;	
			handle->state = 4;
			// printf("--->state:%d\r\n",handle->state);
		}

		break;
	case 4:
		if(handle->ticks - handle->last_ticks > handle->low_level_ticks)
		{
			tls_gpio_write(handle->light_gpio,!handle->active_level);
			handle->last_level = !handle->active_level;
			handle->last_ticks = handle->ticks;	
			handle->state = 3;
			// printf("--->state:%d\r\n",handle->state);
		}
		break;
	}

}

int light_start(struct Light* handle)
{
	struct Light* target = head_handle;
	while(target) {
		if(target == handle) return -1;	//already exist.
		target = target->next;
	}
	handle->next = head_handle;
	head_handle = handle;
	return 0;
}

void light_blink(struct Light* handle,u16 high,u16 low)
{
	handle->keep_ticks = 0;
	handle->state = 3;
	handle->high_level_ticks= high/LIGHT_TICKS;
	handle->low_level_ticks= low/LIGHT_TICKS;
}
void light_blink_timeout(struct Light* handle,u16 high,u16 low,u32 timeout)
{
	handle->state= 3;
	handle->high_level_ticks= high/LIGHT_TICKS;
	handle->low_level_ticks= low/LIGHT_TICKS;
	handle->keep_ticks= timeout/LIGHT_TICKS;
}
void light_on(struct Light* handle)
{
	handle->keep_ticks = 0;
	handle->state= 1;
}
void light_on_timeout(struct Light* handle,u32 timeout)
{
	handle->state= 1;
	handle->keep_ticks= timeout/LIGHT_TICKS;
}
void light_off(struct Light* handle)
{
	handle->keep_ticks = 0;
	handle->state= 2;
}

void light_stop(struct Light* handle)
{
	struct Light** curr;
	for(curr = &head_handle; *curr; ) {
		struct Light* entry = *curr;
		if (entry == handle) {
			*curr = entry->next;
//			free(entry);
		} else
			curr = &entry->next;
	}
}

